ddns-scripts: fixed ovh dns record update
authorDavid Andreoletti <[email protected]>
Tue, 30 Sep 2025 04:51:00 +0000 (12:51 +0800)
committerFlorian Eckert <[email protected]>
Tue, 7 Oct 2025 14:32:37 +0000 (16:32 +0200)
OVH changed its API to update DNS records. It now requires HTTP Basic
Authorization header. As such the default ddns-script method to update
the DNS record is failing. The fix is to move DNS record updates into
its own script/package.

Signed-off-by: David Andreoletti <[email protected]>
net/ddns-scripts/Makefile
net/ddns-scripts/files/usr/lib/ddns/update_ovh_com.sh [new file with mode: 0644]
net/ddns-scripts/files/usr/share/ddns/default/ovh.com.json

index 00f4b971aa4599f2a5604d23406952001589f19b..b1132d893f148b9c044fd1539e81e201a467f644 100644 (file)
@@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk
 
 PKG_NAME:=ddns-scripts
 PKG_VERSION:=2.8.2
-PKG_RELEASE:=78
+PKG_RELEASE:=79
 
 PKG_LICENSE:=GPL-2.0
 
@@ -143,6 +143,21 @@ define Package/ddns-scripts-digitalocean/description
   'option password' the api token generated in the DO panel
 endef
 
+define Package/ddns-scripts-ovh
+  $(call Package/ddns-scripts/Default)
+  TITLE:=Extension for OVH Dynhost
+  DEPENDS:=ddns-scripts +curl +openssl-util
+  PROVIDES:=ddns-scripts_ovh-dynhost
+endef
+
+define Package/ddns-scripts-ovh/description
+  Dynamic DNS Client scripts extension for ovh.com DynHost API.
+  The script directly updates a DNS record using the OVH DynHost API.
+  It requires:
+  'option domain' the dns domain to update the record for (eg. A-record: home.<example.com>)
+  'option username' the dynhost user
+  'option password' the dynhost password
+endef
 
 define Package/ddns-scripts-dnspod
   $(call Package/ddns-scripts/Default)
@@ -423,6 +438,7 @@ define Package/ddns-scripts-services/install
        rm $(1)/usr/share/ddns/default/freedns.42.pl.json
        rm $(1)/usr/share/ddns/default/godaddy.com-v1.json
        rm $(1)/usr/share/ddns/default/digitalocean.com-v2.json
+       rm $(1)/usr/share/ddns/default/ovh.com.json
        rm $(1)/usr/share/ddns/default/dnspod.cn.json
        rm $(1)/usr/share/ddns/default/dnspod.cn-v3.json
        rm $(1)/usr/share/ddns/default/no-ip.com.json
@@ -563,6 +579,23 @@ fi
 exit 0
 endef
 
+define Package/ddns-scripts-ovh/install
+       $(INSTALL_DIR) $(1)/usr/lib/ddns
+       $(INSTALL_BIN) ./files/usr/lib/ddns/update_ovh_com.sh \
+               $(1)/usr/lib/ddns
+
+       $(INSTALL_DIR) $(1)/usr/share/ddns/default
+       $(INSTALL_DATA) ./files/usr/share/ddns/default/ovh.com.json \
+               $(1)/usr/share/ddns/default
+endef
+
+define Package/ddns-scripts-ovh/prerm
+#!/bin/sh
+if [ -z "$${IPKG_INSTROOT}" ]; then
+       /etc/init.d/ddns stop
+fi
+exit 0
+endef
 
 define Package/ddns-scripts-dnspod/install
        $(INSTALL_DIR) $(1)/usr/lib/ddns
@@ -857,6 +890,7 @@ $(eval $(call BuildPackage,ddns-scripts-gcp))
 $(eval $(call BuildPackage,ddns-scripts-freedns))
 $(eval $(call BuildPackage,ddns-scripts-godaddy))
 $(eval $(call BuildPackage,ddns-scripts-digitalocean))
+$(eval $(call BuildPackage,ddns-scripts-ovh))
 $(eval $(call BuildPackage,ddns-scripts-dnspod))
 $(eval $(call BuildPackage,ddns-scripts-dnspod-v3))
 $(eval $(call BuildPackage,ddns-scripts-noip))
diff --git a/net/ddns-scripts/files/usr/lib/ddns/update_ovh_com.sh b/net/ddns-scripts/files/usr/lib/ddns/update_ovh_com.sh
new file mode 100644 (file)
index 0000000..5189868
--- /dev/null
@@ -0,0 +1,32 @@
+# Script for sending user defined updates using the OVH Dynhost API
+# 2025 David Andreoletti <david at andreoletti dot net>
+
+# Options passed from /etc/config/ddns:
+# Domain - the domain name managed by OVH (e.g. example.com)
+# Username - the dynhost username of the domain (e.g. myrouter)
+# Password -  the dynhost password of the domain
+
+. /usr/share/libubox/jshn.sh
+
+# base64 encoding
+http_basic_encoding() {
+       local user="$1"
+       local password="$2"
+       echo "${user}:${password}" | openssl base64 
+}
+
+[ -z "$domain" ] && write_log 14 "Service section not configured correctly! Missing domain name as 'Domain'"
+[ -z "$username" ] && write_log 14 "Service section not configured correctly! Missing username as 'Username'"
+[ -z "$password" ] && write_log 14 "Service section not configured correctly! Missing password as 'Password'"
+
+__STATUS=$(curl -Ss -X GET "https://dns.eu.ovhapis.com/nic/update?system=dyndns&hostname=${domain}&myip=${__IP}" \
+       -H "Authorization: Basic $(http_basic_encoding "$username" "$password")" \
+       -w "%{response_code}\n" -o $DATFILE 2>$ERRFILE)
+
+if [ $? -ne 0 ]; then
+       write_log 14 "Curl failed: $(cat $ERRFILE)"
+       return 1
+elif [ -z $__STATUS ] || [ $__STATUS != 200 ]; then
+       write_log 14 "Curl failed: $__STATUS \novh.com answered: $(cat $DATFILE)"
+       return 1
+fi
index 446093bcecd5d136282cc6722d30e1b60749afdd..1ea3c72d21a793d575e7d5b457745572e33f5322 100644 (file)
@@ -1,11 +1,9 @@
 {
        "name": "ovh.com",
        "ipv4": {
-               "url": "https://[USERNAME]:[PASSWORD]@dns.eu.ovhapis.com/nic/update?system=dyndns&hostname=[DOMAIN]&myip=[IP]",
-               "answer": "good|nochg"
+               "url": "update_ovh_com.sh"
        },
        "ipv6": {
-               "url": "https://[USERNAME]:[PASSWORD]@dns.eu.ovhapis.com/nic/update?system=dyndns&hostname=[DOMAIN]&myip=[IP]",
-               "answer": "good|nochg"
+               "url": "update_ovh_com.sh"
        }
 }